package com.jy.rhin.application.assembler;

import cn.org.chiss.rhin._2015.basic.audit.CodedValueType;
import cn.org.chiss.rhin._2015.basic.audit.*;
import com.jy.framework.base.utils.Converter;
import com.jy.rhin.application.enums.*;
import com.jy.rhin.sdk.dto.audit.*;
import com.jy.rhin.support.interceptor.WsXmlThreadLocal;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Description:
 * @Author: lww
 * @Date: 2022/5/23 17:09
 */
public class AuditAssembler {

    private AuditAssembler() {
    }

    private static final String DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    public static AuditDto convertEnum(AuditDto dto) {
        if (Objects.isNull(dto)) {
            return dto;
        }
        AuditInfoEventDto eventInfo = dto.getEventInfo();
        if (Objects.nonNull(eventInfo)) {
            eventInfo.setCaoZuoLx(code2name(EventActionCodeEnum.class, eventInfo.getCaoZuoLx()));
            eventInfo.setShiJianJg(code2name(EventOutcomeIndicatorEnum.class, eventInfo.getShiJianJg()));
        }
        List<AuditObjectDto> objectDtoList = dto.getObjectDtoList();
        if (!CollectionUtils.isEmpty(objectDtoList)) {
            for (AuditObjectDto auditObjectDto : objectDtoList) {
                auditObjectDto.setMinGanXing(code2name(MinGanXingEnum.class, auditObjectDto.getMinGanXing()));
                auditObjectDto.setObjectJueSe(code2name(ParticipantObjectTypeCodeRoleEnum.class, auditObjectDto.getObjectJueSe()));
                auditObjectDto.setObjectLx(code2name(ParticipantObjectTypeCodeEnum.class, auditObjectDto.getObjectLx()));
                auditObjectDto.setObjectZhouQi(code2name(ParticipantObjectDataLifeCycleEnum.class, auditObjectDto.getObjectZhouQi()));
            }
        }
        List<AuditParticipantDto> participantList = dto.getParticipantList();
        if (!CollectionUtils.isEmpty(participantList)) {
            for (AuditParticipantDto auditParticipantDto : participantList) {
                auditParticipantDto.setWangLuoFwdCode(code2name(NetworkAccessPointTypeCodeEnum.class, auditParticipantDto.getWangLuoFwdCode()));
            }
        }
        return dto;
    }

    private static <T extends BaseEnum> String code2name(Class<T> clazz, String code) {
        if (StringUtils.isBlank(code)) {
            return code;
        }
        if (clazz.isEnum()) {
            T[] enumConstants = clazz.getEnumConstants();
            for (T enumConstant : enumConstants) {
                if (StringUtils.equals(enumConstant.getCode(), code)) {
                    return enumConstant.getName();
                }
            }
        }
        return code;
    }

    public static AuditWrapperDto toDto(AuditMessage auditMessage) {
        AuditWrapperDto dto = new AuditWrapperDto();
        buildEventInfo(auditMessage, dto);
        buildAuditSource(auditMessage, dto);
        buildActiveParticipant(auditMessage, dto);
        buildAuditObject(auditMessage, dto);
        return dto;
    }

    /**
     * 事件信息构建
     *
     * @param auditMessage
     * @param dto
     */
    private static void buildEventInfo(AuditMessage auditMessage, AuditWrapperDto dto) {
        AuditInfoEventDto eventInfo = new AuditInfoEventDto();
        EventIdentificationType eventIdentification = auditMessage.getEventIdentification();
        Date eventTime = Converter.toDate(eventIdentification.getEventDateTime(), DATE_ISO);
        eventInfo.setFaQiSj(eventTime);
        eventInfo.setCaoZuoLx(eventIdentification.getEventActionCode().toString());
        String xml = WsXmlThreadLocal.getXml();
        dto.setXmlText(xml);
        eventInfo.setShiJianJg(eventIdentification.getEventOutcomeIndicator().toString());
        CodedValueType eventIdCode = eventIdentification.getEventID();
        CodedValueTypeDto eventIdCodeDto = new CodedValueTypeDto();
        BeanUtils.copyProperties(eventIdCode, eventIdCodeDto);
        eventInfo.setShiJianBs(eventIdCodeDto);
        CodedValueType codedValueType = eventIdentification.getEventTypeCode().get(0);
        CodedValueTypeDto codedValueTypeDto = new CodedValueTypeDto();
        BeanUtils.copyProperties(codedValueType, codedValueTypeDto);
        eventInfo.setShiJianLx(codedValueTypeDto);
        dto.setEventInfo(eventInfo);
    }

    /**
     * 审计源构建
     *
     * @return
     */
    private static void buildAuditSource(AuditMessage auditMessage, AuditWrapperDto dto) {
        List<AuditSourceIdentificationType> auditSourceIdentification = auditMessage.getAuditSourceIdentification();
        List<AuditSourceDto> sourceList = new ArrayList<>();
        auditSourceIdentification.forEach(auditSourceIdentificationType -> {
            List<CodedValueType> auditSourceTypeCode = auditSourceIdentificationType.getAuditSourceTypeCode();
            CodedValueType codedValueType = auditSourceTypeCode.get(0);
            AuditSourceDto auditSource = new AuditSourceDto();
            auditSource.setBiaoShi(auditSourceIdentificationType.getAuditSourceID());
            auditSource.setWangZhi(auditSourceIdentificationType.getAuditEnterpriseSiteID());
            CodedValueTypeDto codedValueTypeDto = new CodedValueTypeDto();
            BeanUtils.copyProperties(codedValueType, codedValueTypeDto);
            auditSource.setLeiXing(codedValueTypeDto);
            sourceList.add(auditSource);
        });
        dto.setSourceList(sourceList);
    }

    /**
     * 参与者构建
     *
     * @return
     */
    private static void buildActiveParticipant(AuditMessage auditMessage, AuditWrapperDto dto) {
        List<AuditParticipantDto> participantList = new ArrayList<>();
        List<ActiveParticipantType> activeParticipantList = auditMessage.getActiveParticipant();
        activeParticipantList.forEach(activeParticipantType -> {
            CodedValueType codedValueType = activeParticipantType.getRoleIDCode().get(0);
            CodedValueTypeDto codedValueTypeDto = new CodedValueTypeDto();
            BeanUtils.copyProperties(codedValueType, codedValueTypeDto);
            AuditParticipantDto participant = new AuditParticipantDto();
            participant.setJueSe(codedValueTypeDto);
            participant.setUserId(activeParticipantType.getUserID());
            participant.setUserName(activeParticipantType.getUserName());
            participant.setQiTaBs(activeParticipantType.getAlternativeUserID());
            participant.setUserIsRequester(activeParticipantType.getUserIsRequestor());
            participant.setWangLuoFwd(activeParticipantType.getNetworkAccessPointID());
            if (Objects.nonNull(activeParticipantType.getNetworkAccessPointTypeCode())) {
                participant.setWangLuoFwdCode(activeParticipantType.getNetworkAccessPointTypeCode().toString());
            }
            participantList.add(participant);
        });
        dto.setParticipantList(participantList);
    }

    /**
     * 具体参与者对象构建
     *
     * @param auditMessage
     * @param dto
     */
    private static void buildAuditObject(AuditMessage auditMessage, AuditWrapperDto dto) {
        List<ParticipantObjectIdentificationType> participantObjectList = auditMessage.getParticipantObjectIdentification();
        List<AuditObjectDto> objectDtoList = new ArrayList<>();
        for (ParticipantObjectIdentificationType participantObject : participantObjectList) {
            AuditObjectDto auditObject = new AuditObjectDto();
            auditObject.setObjectId(participantObject.getParticipantObjectID());
            auditObject.setObjectLx(participantObject.getParticipantObjectTypeCode().toString());
            auditObject.setObjectJueSe(participantObject.getParticipantObjectTypeCodeRole().toString());
            auditObject.setObjectZhouQi(participantObject.getParticipantObjectDataLifeCycle().toString());
            auditObject.setMinGanXing(participantObject.getParticipantObjectSensitivity());
            CodedValueType codedValueType = participantObject.getParticipantObjectIDTypeCode();
            CodedValueTypeDto codedValueTypeDto = new CodedValueTypeDto();
            BeanUtils.copyProperties(codedValueType, codedValueTypeDto);
            auditObject.setBiaoShiLx(codedValueTypeDto);
            auditObject.setObjectName(participantObject.getParticipantObjectName());
            TypeValuePairType typeValuePairType = participantObject.getParticipantObjectDetail().get(0);
            AuditObjectDto.AuditObjectDesc auditObjectDesc = new AuditObjectDto.AuditObjectDesc();
            auditObjectDesc.setType(typeValuePairType.getType());
            auditObjectDesc.setValue(new String(typeValuePairType.getValue()));
            auditObject.setMiaoShu(auditObjectDesc);
            objectDtoList.add(auditObject);
        }
        dto.setObjectDtoList(objectDtoList);
    }
}
